"""
Fortran type system analysis for CodeMCP framework.

This module provides analysis of Fortran derived types and
the type system including type-bound procedures.
"""

import logging
from typing import Dict, List, Any, Set, Optional
from collections import defaultdict

from ...core.error_handler import AnalysisError, log_info


class DerivedTypeInfo:
    """Information about a Fortran derived type."""
    
    def __init__(self, name: str, line_number: int = 0):
        self.name = name
        self.line_number = line_number
        self.components = []  # List of type components
        self.procedures = []  # Type-bound procedures
        self.extends = None  # Parent type name
        self.is_abstract = False
        self.is_sequence = False
        self.is_bind_c = False
        self.is_parameterized = False  # PDT
        self.parameters = []  # Type parameters for PDT
    
    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary representation."""
        return {
            'name': self.name,
            'line_number': self.line_number,
            'components': self.components,
            'procedures': self.procedures,
            'extends': self.extends,
            'is_abstract': self.is_abstract,
            'is_sequence': self.is_sequence,
            'is_bind_c': self.is_bind_c,
            'is_parameterized': self.is_parameterized,
            'parameters': self.parameters
        }


class TypeAnalyzer:
    """
    Fortran type system analyzer.
    
    Analyzes derived types, type hierarchies, and type-bound procedures.
    """
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.types = {}  # name -> DerivedTypeInfo
        self.type_hierarchy = defaultdict(list)  # parent -> [children]
        self.type_bound_procedures = defaultdict(list)  # type -> [procedures]
    
    def analyze_types(self, parsed_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Analyze types in parsed Fortran data.
        
        Args:
            parsed_data: Parsed Fortran file data
            
        Returns:
            Type analysis results
        """
        try:
            filename = parsed_data.get('filename', 'unknown')
            log_info(f"Analyzing types in {filename}")
            
            # Process derived types
            for type_data in parsed_data.get('types', []):
                self._process_derived_type(type_data)
            
            # Build type hierarchy
            self._build_type_hierarchy()
            
            result = {
                'filename': filename,
                'types': {name: typ.to_dict() for name, typ in self.types.items()},
                'type_hierarchy': dict(self.type_hierarchy),
                'type_bound_procedures': dict(self.type_bound_procedures),
                'statistics': self._compute_statistics()
            }
            
            log_info(f"Type analysis complete for {filename}: "
                    f"{len(self.types)} derived types")
            
            return result
            
        except Exception as e:
            self.logger.error(f"Error analyzing types: {e}")
            raise AnalysisError(f"Type analysis failed: {e}")
    
    def _process_derived_type(self, type_data: Dict[str, Any]):
        """Process a single derived type."""
        name = type_data.get('name', 'unnamed')
        
        type_info = DerivedTypeInfo(
            name=name,
            line_number=type_data.get('line_number', 0)
        )
        
        type_info.components = type_data.get('components', [])
        type_info.procedures = type_data.get('procedures', [])
        type_info.extends = type_data.get('extends')
        type_info.is_abstract = type_data.get('is_abstract', False)
        type_info.is_sequence = type_data.get('is_sequence', False)
        type_info.is_bind_c = type_data.get('is_bind_c', False)
        type_info.parameters = type_data.get('parameters', [])
        type_info.is_parameterized = len(type_info.parameters) > 0
        
        self.types[name] = type_info
        
        # Track type-bound procedures
        if type_info.procedures:
            self.type_bound_procedures[name] = type_info.procedures
    
    def _build_type_hierarchy(self):
        """Build type hierarchy from extends relationships."""
        for type_name, type_info in self.types.items():
            if type_info.extends:
                self.type_hierarchy[type_info.extends].append(type_name)
    
    def _compute_statistics(self) -> Dict[str, Any]:
        """Compute type analysis statistics."""
        total_types = len(self.types)
        abstract_count = len([t for t in self.types.values() if t.is_abstract])
        sequence_count = len([t for t in self.types.values() if t.is_sequence])
        bind_c_count = len([t for t in self.types.values() if t.is_bind_c])
        parameterized_count = len([t for t in self.types.values() if t.is_parameterized])
        extended_count = len([t for t in self.types.values() if t.extends])
        
        return {
            'total_types': total_types,
            'abstract_types': abstract_count,
            'sequence_types': sequence_count,
            'bind_c_types': bind_c_count,
            'parameterized_types': parameterized_count,
            'extended_types': extended_count,
            'root_types': total_types - extended_count
        }